package samfeng.erp.location.service;

import cn.hutool.core.util.StrUtil;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import samfeng.erp.location.controller.vo.*;
import samfeng.erp.location.dal.dataobject.LocationDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import samfeng.erp.location.convert.LocationConvert;
import samfeng.erp.location.dal.mysql.LocationMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
import static samfeng.erp.location.enmus.ErrorCodeConstants.LOCATION_IS_EXISTS;
import static samfeng.erp.location.enmus.ErrorCodeConstants.LOCATION_NOT_EXISTS;

/**
 * 仓库库位 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class LocationServiceImpl implements LocationService {

    @Resource
    private LocationMapper locationMapper;

    private String completeName = "";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createLocation(LocationCreateReqVO createReqVO) {
        this.checkLocationExists(createReqVO.getName());
        // 插入
        LocationDO location = LocationConvert.INSTANCE.convert(createReqVO);
        location.setCompleteName(getFinalCompleteName(location));
        locationMapper.insert(location);
        // 返回
        return location.getId();
    }

    @Override
    public void updateLocation(LocationUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateLocationExists(updateReqVO.getId());
        // 更新
        LocationDO updateObj = LocationConvert.INSTANCE.convert(updateReqVO);
        updateObj.setCompleteName(getFinalCompleteName(updateObj));
        locationMapper.updateById(updateObj);
    }

    @Override
    public void deleteLocation(Long id) {
        // 校验存在
        this.validateLocationExists(id);
        // 删除
        locationMapper.deleteById(id);
    }

    private void validateLocationExists(Long id) {
        if (locationMapper.selectById(id) == null) {
            throw exception(LOCATION_NOT_EXISTS);
        }
    }

    @Override
    public LocationDO getLocation(Long id) {
        return locationMapper.selectById(id);
    }

    @Override
    public List<LocationDO> getLocationList(Collection<Long> ids) {
        return locationMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<LocationDO> getLocationPage(LocationPageReqVO pageReqVO) {
        return locationMapper.selectPage(pageReqVO);
    }

    @Override
    public List<LocationDO> getLocationList(LocationExportReqVO exportReqVO) {
        return locationMapper.selectList(exportReqVO);
    }

    /**
     * 查询库位列表（排除节点）
     */
    @Override
    public List<LocationRespVO> excludeChild(Long id, Long warehouseId) {
        List<LocationDO> cList = locationMapper.excludeSelectList(id, warehouseId);
        return LocationConvert.INSTANCE.convertList(cList);
    }

    private String getFinalCompleteName(LocationDO stockLocation) {
        List<LocationDO> stockLocationList = locationMapper.selectList();
        this.completeName = "";
        loopGetCompleteName(stockLocation, stockLocationList);
        return this.completeName;
    }

    private void loopGetCompleteName(LocationDO currentLocation, List<LocationDO> stockLocations) {
        if (null != currentLocation.getParentId() && currentLocation.getParentId()!=0) {
            for (LocationDO location : stockLocations) {
                if (currentLocation.getParentId().equals(location.getId())) {
                    if (StrUtil.isNotEmpty(location.getCompleteName())) {
                        this.completeName = "/" + currentLocation.getName() + this.completeName;
                        if (location.getParentId() != 0) {
                            loopGetCompleteName(location, stockLocations);
                        } else {
                            this.completeName = location.getCompleteName() + this.completeName;
                        }
                    } else {
                        this.completeName = location.getCompleteName() + "/" +currentLocation.getName();
                        break;
                    }
                }
            }
        } else {
            this.completeName = "/" + currentLocation.getName() + this.completeName;
        }
    }

    @VisibleForTesting
    private void checkLocationExists(String name) {
        if (name == null) {
            return;
        }
        LocationDO location = locationMapper.selectOne("name", name);
        if (location != null) {
            throw exception(LOCATION_IS_EXISTS);
        }
    }
}
